<?php

require('errors/ModelException.php');
require('RootModel.php');
require('PathModel.php');
require('ScalarModel.php');
require('ObjectModel.php');
require('ArrayModel.php');
require('ModelBuilder.php');

class DB
{

    static function build($dir, $db)
    {
        $theDB = new DB();
        self::buildModels($dir, $db, $theDB);
        return $theDB;
    }

    //$dir末尾要带'/', $db, $theDB 可能是孩子
    private static function buildModels($dir, $db, $theDB)
    {
//		$db = (new MongoClient())->test;

        $subDirs = [];

        foreach (scandir($dir) as $f) {
            if ($f == '.' || $f == '..') continue;
            $path = $dir . $f;
            if (is_dir($path)) {
                $subDirs[] = $f;
                continue;
            }
            require_once($path);
            $modelClass = preg_replace('/\.php$/', '', $f);
            $modelName = lcfirst(preg_replace('/Model$/', '', $modelClass));

            $theDB->$modelName = ModelBuilder::buildRootModel(
                self::fullSchema($modelClass::model), $db->$modelName);
        }

        foreach ($subDirs as $subDir) {
            if (!isset($theDB->$subDir)) $theDB->$subDir = new stdClass();
            self::buildModels($dir . $subDir . '/', $db->$subDir, $theDB->$subDir);
        }
    }

    static function fullSchema($model)
    {
        return [
            'id' => 'string',
            'stat' => [
                'createTime' => 'integer',
                'updateTime' => 'integer',
                'visit' => 'integer'
            ]
        ] + $model;
    }

    function __toString()
    {
        $lines = [];
        self::iterateObject($this, 0, $lines);
        return join("\n", $lines);
    }

    static function iterateObject($o, $indent, & $lines)
    {
        foreach ($o as $key => $value) {
            $lines[] = str_repeat("\t", $indent) . $key . '(' . get_class($value) . ')';
            self::iterateObject($value, $indent + 1, $lines);
        }
    }

}